all repos — caroster @ 86829d3374bcddffb3063bb7abc10cf1975bea87

[Octree] Group carpool to your event https://caroster.io

frontend/pages/e/[uuid]/details.tsx (view raw)

  1import moment from 'moment';
  2import Button from '@mui/material/Button';
  3import Box from '@mui/material/Box';
  4import Link from '@mui/material/Link';
  5import Paper from '@mui/material/Paper';
  6import Divider from '@mui/material/Divider';
  7import Container from '@mui/material/Container';
  8import TextField from '@mui/material/TextField';
  9import Typography from '@mui/material/Typography';
 10import {useTheme} from '@mui/material/styles';
 11import {DatePicker} from '@mui/x-date-pickers/DatePicker';
 12import {PropsWithChildren, useState} from 'react';
 13import {useTranslation} from 'react-i18next';
 14import pageUtils from '../../../lib/pageUtils';
 15import ShareEvent from '../../../containers/ShareEvent';
 16import useEventStore from '../../../stores/useEventStore';
 17import useToastStore from '../../../stores/useToastStore';
 18import useSettings from '../../../hooks/useSettings';
 19import EventLayout, {TabComponent} from '../../../layouts/Event';
 20import {
 21  EventByUuidDocument,
 22  useUpdateEventMutation,
 23} from '../../../generated/graphql';
 24import SupportCaroster from '../../../containers/SupportCaroster';
 25
 26interface Props {
 27  eventUUID: string;
 28  announcement?: string;
 29}
 30
 31const Page = (props: PropsWithChildren<Props>) => {
 32  return <EventLayout {...props} Tab={DetailsTab} />;
 33};
 34
 35const DetailsTab: TabComponent = ({}) => {
 36  const {t} = useTranslation();
 37  const theme = useTheme();
 38  const settings = useSettings();
 39  const [updateEvent] = useUpdateEventMutation();
 40  const addToast = useToastStore(s => s.addToast);
 41  const setEventUpdate = useEventStore(s => s.setEventUpdate);
 42  const event = useEventStore(s => s.event);
 43  const [isEditing, setIsEditing] = useState(false);
 44  const idPrefix = isEditing ? 'EditEvent' : 'Event';
 45
 46  const onSave = async e => {
 47    try {
 48      const {uuid, ...data} = event;
 49      const {id, travels, waitingPassengers, __typename, ...input} = data;
 50      await updateEvent({
 51        variables: {uuid, eventUpdate: input},
 52        refetchQueries: ['eventByUUID'],
 53      });
 54      setIsEditing(false);
 55    } catch (error) {
 56      console.error(error);
 57      addToast(t('event.errors.cant_update'));
 58    }
 59  };
 60  const sectionSx = {
 61    marginBottom: theme.spacing(2),
 62    width: '540px',
 63    maxWidth: '100%',
 64    paddingX: theme.spacing(2),
 65  };
 66
 67  const modifyButton = isEditing ? (
 68    <Button
 69      variant="contained"
 70      color="primary"
 71      sx={{position: 'absolute', right: theme.spacing(2)}}
 72      onClick={onSave}
 73    >
 74      {t('event.details.save')}
 75    </Button>
 76  ) : (
 77    <Button
 78      variant="text"
 79      color="primary"
 80      sx={{position: 'absolute', right: theme.spacing(2)}}
 81      onClick={() => setIsEditing(true)}
 82    >
 83      {t('event.details.modify')}
 84    </Button>
 85  );
 86
 87  if (!event) return null;
 88
 89  return (
 90    <Box
 91      sx={{
 92        position: 'relative',
 93        paddingLeft: '80px',
 94
 95        [theme.breakpoints.down('md')]: {
 96          paddingLeft: 0,
 97          paddingBottom: '80px',
 98        },
 99      }}
100    >
101      <Container maxWidth="sm" sx={{marginTop: theme.spacing(6)}}>
102        <Paper sx={{position: 'relative', padding: theme.spacing(2)}}>
103          {modifyButton}
104          <Box sx={sectionSx}>
105            <Typography variant="h6">{t('event.fields.name')}</Typography>
106            {isEditing ? (
107              <TextField
108                fullWidth
109                value={event.name}
110                onChange={e => setEventUpdate({name: e.target.value})}
111                name="name"
112                id="EditEventName"
113              />
114            ) : (
115              <Typography variant="body1" id={`${idPrefix}Name`}>
116                {event.name ?? t('event.fields.empty')}
117              </Typography>
118            )}
119          </Box>
120          <Box sx={sectionSx}>
121            <Typography variant="h6">{t('event.fields.date')}</Typography>
122            {isEditing ? (
123              <DatePicker
124                renderInput={props => (
125                  <TextField
126                    {...props}
127                    id={`${idPrefix}Date`}
128                    fullWidth
129                    placeholder={t('event.fields.date_placeholder')}
130                  />
131                )}
132                inputFormat="DD/MM/yyyy"
133                value={event.date}
134                onChange={date =>
135                  setEventUpdate({
136                    date: !date ? null : moment(date).format('YYYY-MM-DD'),
137                  })
138                }
139              />
140            ) : (
141              <Typography variant="body1" id={`${idPrefix}Date`}>
142                {event.date
143                  ? moment(event.date).format('DD/MM/YYYY')
144                  : t('event.fields.empty')}
145              </Typography>
146            )}
147          </Box>
148          <Box sx={sectionSx}>
149            <Typography variant="h6">{t('event.fields.address')}</Typography>
150            {isEditing ? (
151              <TextField
152                fullWidth
153                multiline
154                maxRows={4}
155                inputProps={{maxLength: 250}}
156                helperText={`${event.address?.length ?? 0}/250`}
157                defaultValue={event.address}
158                value={event.address}
159                onChange={e => setEventUpdate({address: e.target.value})}
160                id={`${idPrefix}Address`}
161                name="address"
162              />
163            ) : (
164              <Typography variant="body1" id={`${idPrefix}Address`}>
165                {event.address ? (
166                  <Link
167                    target="_blank"
168                    rel="noreferrer"
169                    href={`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(
170                      event.address
171                    )}`}
172                    onClick={e => e.preventDefault}
173                  >
174                    {event.address}
175                  </Link>
176                ) : (
177                  t('event.fields.empty')
178                )}
179              </Typography>
180            )}
181          </Box>
182          <Box sx={sectionSx}>
183            <Typography variant="h6">
184              {t('event.fields.description')}
185            </Typography>
186            {isEditing ? (
187              <TextField
188                fullWidth
189                multiline
190                maxRows={4}
191                inputProps={{maxLength: 250}}
192                helperText={`${event.description?.length || 0}/250`}
193                defaultValue={event.description}
194                value={event.description || ''}
195                onChange={e => setEventUpdate({description: e.target.value})}
196                id={`${idPrefix}Description`}
197                name="description"
198              />
199            ) : (
200              <Typography variant="body1" id={`${idPrefix}Description`}>
201                {event.description ?? t('event.fields.empty')}
202              </Typography>
203            )}
204          </Box>
205          <Box sx={sectionSx}>
206            <Typography variant="h6">{t('event.fields.link')}</Typography>
207            <Typography>{t('event.fields.link_desc')}</Typography>
208          </Box>
209          <Box pt={4} pb={2} justifyContent="center" display="flex">
210            <ShareEvent title={`Caroster ${event.name}`} />{' '}
211          </Box>
212        </Paper>
213        <Box mt={4} display="flex" justifyContent="center">
214          <SupportCaroster />
215        </Box>
216      </Container>
217    </Box>
218  );
219};
220
221export const getServerSideProps = pageUtils.getServerSideProps(
222  async (context, apolloClient) => {
223    const {uuid} = context.query;
224    const {host = ''} = context.req.headers;
225    let event = null;
226
227    // Fetch event
228    try {
229      const {data} = await apolloClient.query({
230        query: EventByUuidDocument,
231        variables: {uuid},
232      });
233      event = data?.eventByUUID?.data;
234    } catch (error) {
235      return {
236        notFound: true,
237      };
238    }
239
240    return {
241      props: {
242        eventUUID: uuid,
243        metas: {
244          title: event?.attributes?.name || '',
245          url: `https://${host}${context.resolvedUrl}`,
246        },
247      },
248    };
249  }
250);
251export default Page;